﻿/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#ifndef MK_HTTP_API_H
#define MK_HTTP_API_H
#include "MkHttp/MkHttpServer.h"
#include "MkHttp/MkHttpRequest.h"
#include <json/json.h>

typedef MkFunction<void(Uint32 ErrorCode, const Json::Value &ResBody)>   MkHttpResponseJsonCb;
class CMkThread;
class MkApi CMkHttpApi : public CMkHttpServer
{
    typedef MkFunction<void(const MkHttpBodyType& BodyType, const MkString &ResBody)>   HttpResponseCb;
    typedef struct _http_request_param
    {
        CMkHttpRequest      Request;
        HttpResponseCb      ResCb;
    }MkHttpRequestParam;
public:
    CMkHttpApi(CMkEventPool* pEventPool, CMkTimer* pTimer);
    virtual ~CMkHttpApi();

    Uint32 StartServer(Uint16 Port, const MkString& Host = "", Uint32 TaskCount = 10);
    Uint32 BroadCastMsg(const MkString& Msg);
    //Serial the task can not do in multi-thread
    Uint32 AddTaskPath(const MkHttpMethod& Method, const MkString& Path, BOOL bSerial = FALSE);

    void SetUserPass(const MkString &UserName, const MkString &Password);
    void SetWebSocketPath(const MkString& Path) { m_WebSocketPath = Path; }
    void SetApiUriPrefix(const MkString& Uri) { m_ApiUriPrefix = Uri; }
    void SetWhitePath(const MkString& Path) { m_WhitePath = m_ApiUriPrefix + Path; }
    void SetWebSocketAccessKey(const MkString& Key);
    void SetMaxWsConnectorSize(const Uint32& MaxSize);

    const MkString &GetWebSocketPath() const { return m_WebSocketPath; }
    const MkString &GetUserName() const { return m_UserName; }
    const MkString &GetPassword() const { return m_Password; }
    const MkString &GetApiUriPrefix() const { return m_ApiUriPrefix; }
    const MkString &GetWhitePath() const { return m_WhitePath; }
    const MkString &GetWebSocketAccessKey() const { return m_WebSocketAccessKey; }
    const Uint32& GetMaxWsConnectorSize() const { return m_MaxWsConnectorSize; }

    Uint32 StopServer();
    virtual Uint32 OnRequestJsonParse(const MkHttpMethod& Method, const MkString& Path, const MkMapString& MapQuery, const Json::Value& JsonReq, const MkHttpResponseJsonCb& cb);
    virtual Uint32 OnWebSockekAccessed(CMkHttpSession* pSession);
protected:
    virtual Uint32 OnRecvRequest(CMkHttpSession* pSession, const CMkHttpRequest& Request) override;
    virtual Uint32 OnWebsocketRecved(CMkHttpSession* pSession, const MkString& Message) override;
    virtual Uint32 OnWebsocketClosed(CMkHttpSession* pSession) override;
    virtual Uint32 OnWebsocketConnected(CMkHttpSession* pSession);
private:
    Uint32 DoTaskThread();
    Uint32 DoSerialTaskThread();
private:
    Uint32 HttpRequestParse(const CMkHttpRequest& Request, const HttpResponseCb& cb);
    Uint32 DoHttpRequestParse(const CMkHttpRequest& Request, const HttpResponseCb& cb);
    Uint32 ResponseMessage(Uint32 ErrorCode, const Json::Value &ResBody, const HttpResponseCb& cb);

    MkHttpStatusCode UploadRequest(const CMkHttpRequest& Request, const MkString& FilePath);
    MkHttpStatusCode DeleteRequest(const CMkHttpRequest& Request, const MkString& FilePath);
    MkHttpStatusCode UpdateRequest(const CMkHttpRequest& Request, const MkString& FilePath);
    Uint32 GetPathParam(const MkHttpMethod& Method, const MkString& Path, BOOL &bTask, BOOL &bSerial);
    Uint32 CheckPathInMap(const MkString& Path, const MkMap<MkString, Uint32>& MapPath, BOOL &bSerial);
private:
    MkString                                    m_UserName;
    MkString                                    m_Password;
    MkString                                    m_BaseAuthor;
    MkString                                    m_WhitePath;
    MkString                                    m_ApiUriPrefix;
    MkString                                    m_WebSocketPath;

    Uint32                                      m_TaskThreadCount;
    MkVector<CMkThread*>                        m_VecTaskThread;
    CMkThread                                   m_SerialThread;
    CMkQueue<MkHttpRequestParam>                m_RequestQueue;
    CMkQueue<MkHttpRequestParam>                m_SerialQueue;
    BOOL                                        m_TaskRun;
    BOOL                                        m_HasSerialTask;
    MkMap<MkString, Uint32>                     m_MapGetTaskPath;  //key path  value bSerial
    MkMap<MkString, Uint32>                     m_MapPostTaskPath;
    MkMap<MkString, Uint32>                     m_MapPutTaskPath;
    MkMap<MkString, Uint32>                     m_MapDeleteTaskPath;

    CMkLock                                     m_WsClientLock;
    Uint32                                      m_MaxWsConnectorSize;
    MkVector<CMkHttpSession*>                   m_VecWsSession;
    MkString                                    m_WebSocketAccessKey;
};

#endif
